package com.nut.spp.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nut.spp.api.resp.MenuVo;
import com.nut.spp.common.Result;
import com.nut.spp.entity.SysMenu;
import com.nut.spp.entity.SysRoleMenu;
import com.nut.spp.mapper.SysMenuMapper;
import com.nut.spp.mapper.SysRoleMenuMapper;
import com.nut.spp.service.SysMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class SysMenuServiceImpl implements SysMenuService {

    @Autowired
    private SysMenuMapper sysMenuMapper;

    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;

    public static final ConcurrentHashMap<Integer, List<String>> CACHE = new ConcurrentHashMap<>();

//    @Override
//    public Result<IPage<SysMenu>> list(String name, Integer pageNo, Integer pageSize) {
//        Page<SysMenu> page = new Page<>();
//        page.setSize(pageSize);
//        page.setCurrent(pageNo);
//
//        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
//        if (StringUtils.hasLength(name)) {
//            queryWrapper.like(SysMenu::getName, name);
//        }
//
//        IPage<SysMenu> list = baseMapper.selectPage(page, queryWrapper);
//        return Result.ok(list);
//    }

    @Override
    public List<SysMenu> list(String name) {
        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.hasLength(name)) {
            queryWrapper.like(SysMenu::getName, name);
        }
        queryWrapper.orderByAsc(SysMenu::getSort);
        return sysMenuMapper.selectList(queryWrapper);
    }

    @Override
    public SysMenu getById(Integer id) {
        return sysMenuMapper.selectById(id);
    }

    @Override
    public List<SysMenu> getByPid(Integer pid) {
        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysMenu::getPid, pid);
        queryWrapper.orderByAsc(SysMenu::getSort);
        return sysMenuMapper.selectList(queryWrapper);
    }

    @Override
    public List<MenuVo> getSuperior(Integer id, List<MenuVo> menus) {

        if (id == null) {
            return getByPidVo(0);
        }

        SysMenu menu = sysMenuMapper.selectById(id);
        Integer pid = menu.getPid();
        if (pid == 0) {
            menus.addAll(getByPidVo(0));
            return menus;
        }
        menus.addAll(getByPidVo(pid));
        return getSuperior(pid, menus);
    }

    private List<MenuVo> getByPidVo(Integer pid) {
        List<SysMenu> menus = getByPid(pid);
        ArrayList<MenuVo> list = new ArrayList<>();
        for (SysMenu menu : menus) {
            MenuVo menuVo = new MenuVo();
            menuVo.setId(menu.getId());
            menuVo.setPid(menu.getPid());
            menuVo.setTitle(menu.getTitle());
            list.add(menuVo);
        }
        return list;
    }

    @Override
    public List<MenuVo> buildTree(List<MenuVo> menus) {

        ArrayList<MenuVo> list = new ArrayList<>(menus.size());

        for (MenuVo menu : menus) {
            if (menu.getPid() == 0) {
                list.add(menu);
            }

            for (MenuVo sysMenu : menus) {
                if (sysMenu.getId().equals(menu.getPid())) {
                    if (menu.getChild() == null) {
                        menu.setChild(new ArrayList<>());
                    }
                    menu.getChild().add(sysMenu);
                }
            }
        }

        return list;
    }

    @Override
    public void save(SysMenu sysMenu) {
        sysMenuMapper.insert(sysMenu);
        updateSubCount(sysMenu.getPid());
    }

    @Override
    public void updateById(SysMenu sysMenu) {
        sysMenuMapper.updateById(sysMenu);
        updateSubCount(sysMenu.getPid());
    }

    @Override
    @Cacheable
    public List<String> getPermissionByRoleId(Integer roleId) {
        List<String> cache = CACHE.get(roleId);
        if (cache == null) {
            List<String> permissions = sysMenuMapper.getPermissionByRoleId(roleId);
            CACHE.putIfAbsent(roleId, permissions);
            return permissions;
        }
        return cache;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result deleteByIds(Set<Integer> ids) {

        for (Integer id : ids) {
            SysMenu sysMenu = sysMenuMapper.selectById(id);
            sysMenuMapper.deleteById(id);
            updateSubCount(sysMenu.getPid());
        }

//        sysMenuMapper.deleteBatchIds(ids);

        for (Integer id : ids) {
            //删除菜单关联的角色
            sysRoleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getMenuId, id));
        }

        return Result.ok();
    }


    /**
     * 更新父节点的 是否有子节点标识
     * @param pid
     */
    private void updateSubCount(Integer pid) {
        if (pid == null || pid == 0) {
            return;
        }

        Integer count = sysMenuMapper.selectCount(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getPid, pid));

        SysMenu sysMenu = new SysMenu();
        sysMenu.setId(pid);
        sysMenu.setSubCount(count);
        sysMenuMapper.updateById(sysMenu);
    }
}
